if ( unlikely(info->foreign != NULL) )
{
- put_domain(info->foreign);
+ rcu_unlock_domain(info->foreign);
info->foreign = NULL;
}
}
switch ( domid )
{
case DOMID_IO:
- get_knownalive_domain(dom_io);
- info->foreign = dom_io;
+ info->foreign = rcu_lock_domain(dom_io);
break;
default:
MEM_LOG("Dom %u cannot set foreign dom", d->domain_id);
}
else
{
- info->foreign = e = get_domain_by_id(domid);
+ info->foreign = e = rcu_lock_domain_by_id(domid);
if ( e == NULL )
{
switch ( domid )
{
case DOMID_XEN:
- get_knownalive_domain(dom_xen);
- info->foreign = dom_xen;
+ info->foreign = rcu_lock_domain(dom_xen);
break;
case DOMID_IO:
- get_knownalive_domain(dom_io);
- info->foreign = dom_io;
+ info->foreign = rcu_lock_domain(dom_io);
break;
default:
MEM_LOG("Unknown domain '%u'", domid);
/* A page is dirtied when its pin status is set. */
mark_dirty(d, mfn);
+ /* We can race domain destruction (domain_relinquish_resources). */
+ if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) &&
+ test_bit(_DOMF_dying, &FOREIGNDOM->domain_flags) &&
+ test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+ put_page_and_type(page);
+
break;
case MMUEXT_UNPIN_TABLE:
rcu_read_unlock(&domlist_read_lock);
}
+static inline struct domain *rcu_lock_domain(struct domain *d)
+{
+ rcu_read_lock(d);
+ return d;
+}
+
static inline struct domain *rcu_lock_current_domain(void)
{
- rcu_read_lock(&domlist_read_lock);
- return current->domain;
+ return rcu_lock_domain(current->domain);
}
struct domain *get_domain_by_id(domid_t dom);